﻿using System;
using System.Runtime.Serialization;
using MugenMvvmToolkit.Interfaces;
using MugenMvvmToolkit.Models;
using MugenMvvmToolkit.Utils;

namespace MugenMvvmToolkit.Infrastructure
{
    /// <summary>
    ///     Represents the class that provides methods for transiting one state to another state.
    /// </summary>
#if WPF
    [Serializable]
#endif
    [DataContract]
    public class DefaultStateTransitionProvider : IStateTransitionProvider
    {
        #region Implementation of IStateTransitionProvider

        /// <summary>
        ///     Changes state from one state to another state.
        /// </summary>
        /// <param name="from">The specified state from.</param>
        /// <param name="to">The specified state to.</param>
        /// <param name="validateState">The flag indicating that state will be validated before assigned.</param>
        /// <returns>An instance of state, if any.</returns>
        public EntityState ChangeState(EntityState @from, EntityState to, bool validateState)
        {
            switch (from)
            {
                case EntityState.Unchanged:
                    switch (to)
                    {
                        case EntityState.Added:
                            if (validateState)
                                Thrower.NotConvertableState(from, to);
                            return to;
                        default:
                            return to;
                    }
                case EntityState.Added:
                    switch (to)
                    {
                        case EntityState.Unchanged:
                            if (validateState)
                                Thrower.NotConvertableState(from, to);
                            return to;
                        case EntityState.Deleted:
                            return EntityState.Detached;
                        case EntityState.Modified:
                            return EntityState.Added;
                        default:
                            return to;
                    }
                case EntityState.Deleted:
                    switch (to)
                    {
                        case EntityState.Unchanged:
                            if (validateState)
                                Thrower.NotConvertableState(from, to);
                            return to;
                        case EntityState.Added:
                            if (validateState)
                                Thrower.NotConvertableState(from, to);
                            return to;
                        case EntityState.Modified:
                            if (validateState)
                                Thrower.NotConvertableState(from, to);
                            return to;
                        default:
                            return to;
                    }
                case EntityState.Modified:
                    switch (to)
                    {
                        case EntityState.Unchanged:
                            if (validateState)
                                Thrower.NotConvertableState(from, to);
                            return to;
                        case EntityState.Added:
                            if (validateState)
                                Thrower.NotConvertableState(from, to);
                            return to;
                        default:
                            return to;
                    }
                case EntityState.Detached:
                    return to;
                default:
                    Thrower.EnumOutOfRange("from", from);
                    return EntityState.Detached;
            }
        }

        #endregion
    }
}